package com.jy.oms.framework.asyn.task.checker;

import com.jy.oms.framework.asyn.task.checker.model.ExecutorCheckParam;
import com.jy.oms.framework.asyn.task.checker.model.ExecutorCheckResult;
import com.jy.oms.framework.util.SpringUtil;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * 任务通用链式校验执行器
 *
 * @author liuquan
 */
public class TaskExecutorChainChecker implements IExecutorChecker {
    private static Logger logger = LoggerFactory.getLogger(TaskExecutorChainChecker.class);
    private static List<IExecutorChecker> checkerList = new ArrayList<>();
    private static TaskExecutorChainChecker instance = new TaskExecutorChainChecker();

    private TaskExecutorChainChecker() {
    }

    public static TaskExecutorChainChecker getInstance() {
        return instance;
    }

    public void init() {
        checkerList.add(SpringUtil.getBean(ExecuteTimeRulesChecker.class));
        checkerList.add(SpringUtil.getBean(RateLimitChecker.class));

        //加载业务自定义任务校验执行器
        Map<String, IBusinessExecutorChecker> businessBeanMap = SpringUtil
                .getBeansOfType(IBusinessExecutorChecker.class);
        if (MapUtils.isNotEmpty(businessBeanMap)) {
            for (Map.Entry<String, IBusinessExecutorChecker> entry : businessBeanMap.entrySet()) {
                checkerList.add(entry.getValue());
            }
        }

        //优先级排序，优先级高的先执行校验
        checkerList.sort(Comparator.comparing(IExecutorChecker::getExecutorCheckerOrder));
        checkerList.add(SpringUtil.getBean(TaskExclusiveChecker.class));
        //任务状态检查器放在最后执行校验
        checkerList.add(SpringUtil.getBean(TaskRunningChecker.class));
    }

    @Override
    public ExecutorCheckResult canExecute(ExecutorCheckParam executorCheckParam) {
        try {
            for (IExecutorChecker checker : checkerList) {
                ExecutorCheckResult checkResult = checker.canExecute(executorCheckParam);
                if (!checkResult.isResult()) {
                    return checkResult;
                }
            }

            return ExecutorCheckResult.TRUE;
        } catch (Exception e) {
            logger.error("check error.", e);
        }

        return ExecutorCheckResult.FALSE;
    }

}
